#pragma once

#include "app/app.hpp"
// MySQL协议常量
const int MYSQL_PORT = 3307;
const int MAX_PACKET_SIZE = 16777215;
const int DEFAULT_PROTOCOL_VERSION = 10;

// 客户端连接结构
struct ClientConnection {
    int socket;
    std::string username;
    std::string database;
    std::string client_address;
    std::chrono::steady_clock::time_point connected_time;
    bool authenticated;
    uint64_t sessionId;
};

class MySQLServer {
public:
    uint64_t mNextSessionId = 1;
    std::unordered_map<std::string,Session> mSessions{};
    MySQLServer(int port = MYSQL_PORT) : port(port), running(false) {
#ifdef _WIN32
        // 设置控制台编码为UTF-8
        if (!SetConsoleOutputCP(CP_UTF8) || !SetConsoleCP(CP_UTF8)) {
            // 如果UTF-8设置失败，使用默认编码
            std::cout << "Warning: UTF-8 encoding not available, using default encoding\n";
        }

        WSADATA wsa;
        if (WSAStartup(MAKEWORD(2,2), &wsa) != 0) {
            std::cerr << "WSAStartup failed\n";
            return;
        }
#endif
    }

    ~MySQLServer() {
        stop();
#ifdef _WIN32
        WSACleanup();
#endif
    }

    void start() {
        // 创建socket
        server_fd = socket(AF_INET, SOCK_STREAM, 0);
        if (server_fd < 0) {
            std::cerr << "Socket creation failed\n";
            return;
        }

        // 设置socket选项
        int opt = 1;
#ifdef _WIN32
        setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, (char*)&opt, sizeof(opt));
#else
        setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
#endif

        // 绑定端口
        sockaddr_in address;
        address.sin_family = AF_INET;
        address.sin_addr.s_addr = INADDR_ANY;
        address.sin_port = htons(port);

        if (bind(server_fd, (sockaddr*)&address, sizeof(address)) < 0) {
            std::cerr << "Bind failed on port " << port << std::endl;
            return;
        }

        // 开始监听
        if (listen(server_fd, 10) < 0) {
            std::cerr << "Listen failed\n";
            return;
        }

        running = true;
        std::cout << "MySQL服务器启动成功，监听端口: " << port << std::endl;
        std::cout << "等待客户端连接...\n" << std::endl;

        // 接受客户端连接
        while (running) {
            sockaddr_in client_addr;
            socklen_t client_len = sizeof(client_addr);
            int client_socket = accept(server_fd, (sockaddr*)&client_addr, &client_len);

            if (client_socket < 0) {
                if (running) {
                    std::cerr << "Accept failed\n";
                }
                continue;
            }

            // 获取客户端地址
            char client_ip[INET_ADDRSTRLEN];
            inet_ntop(AF_INET, &client_addr.sin_addr, client_ip, INET_ADDRSTRLEN);
            std::string client_address = std::string(client_ip) + ":" + std::to_string(ntohs(client_addr.sin_port));

            std::cout << "新客户端连接: " << client_address << std::endl;

            // 创建新线程处理客户端连接
            std::thread client_thread(&MySQLServer::handle_connection, this, client_socket, client_address);
            client_thread.detach();
        }
    }

    void stop() {
        running = false;
        if (server_fd >= 0) {
#ifdef _WIN32
            closesocket(server_fd);
#else
            close(server_fd);
#endif
            server_fd = -1;
        }
    }

private:
    void handle_connection(int client_socket, const std::string& client_address) {
        ClientConnection client;
        client.socket = client_socket;
        client.client_address = client_address;
        client.authenticated = false;
        client.connected_time = std::chrono::steady_clock::now();

        try {
            // 发送握手包
            if (!send_handshake(client)) {
                std::cerr << "发送握手包失败: " << client_address << std::endl;
                close_client(client);
                return;
            }

            // 处理认证
//            if (!handle_authentication(client)) {
//                std::cerr << "认证失败: " << client_address << std::endl;
//                close_client(client);
//                return;
//            }
            // ... 握手/认证成功后：
//            auto sess = std::make_shared<Session>();
//            sess->sessionId = nextSessionId++;
//            sess->socket = client_socket;
//            sess->connectedTime = std::chrono::steady_clock::now();
//            sess->user = client.username;     // 认证解析到的用户名
//            sess->database = client.database; // 登录包/后续 USE 语句
            Session sess{};
            sess.sessionId = mNextSessionId++;;
            sess.connectedTime = std::chrono::steady_clock::now();
            sess.socket = client_socket;
            sess.user = "root";
            sess.database = "pixel";
//            sess.user = client.username;;
//            sess.database = client.database;;
            mSessions.emplace(std::to_string(sess.sessionId), std::move(sess));


            client.sessionId = sess.sessionId;
            client.authenticated = true;
            std::cout << "客户端认证成功: " << client_address << " (用户: " << client.username << ")" << std::endl;

            // 添加客户端到连接列表
            {
                std::lock_guard<std::mutex> lock(clients_mutex);
                clients.push_back(client);
            }

            // 处理客户端命令
            handle_client_commands(client);

        } catch (const std::exception& e) {
            std::cerr << "处理客户端连接异常: " << e.what() << " - " << client_address << std::endl;
        }

        // 清理连接
        close_client(client);
    }

    bool send_handshake(ClientConnection& client) {
        // 简化的MySQL握手包
        std::string handshake = "MySQL mock server ready\n";
        return send(client.socket, handshake.c_str(), handshake.length(), 0) > 0;
    }

    bool handle_authentication(ClientConnection& client) {
        char buffer[1024] = {0};
        int bytes_received = recv(client.socket, buffer, sizeof(buffer) - 1, 0);

        if (bytes_received <= 0) {
            return false;
        }

        // 解析认证数据 (简化版)
        std::string auth_data(buffer);

        // 查找用户名和密码 (假设格式: username:password:database)
        size_t pos1 = auth_data.find(':');
        if (pos1 == std::string::npos) {
            return false;
        }

        client.username = auth_data.substr(0, pos1);
        size_t pos2 = auth_data.find(':', pos1 + 1);
        if (pos2 == std::string::npos) {
            return false;
        }

        std::string password = auth_data.substr(pos1 + 1, pos2 - pos1 - 1);
        client.database = auth_data.substr(pos2 + 1);

        // 简单的认证检查 (实际应用中应该使用数据库验证)
        if (client.username == "root" && password == "password") {
            std::string response = "OK\n";
            return send(client.socket, response.c_str(), response.length(), 0) > 0;
        } else if (client.username == "testuser" && password == "testpass") {
            std::string response = "OK\n";
            return send(client.socket, response.c_str(), response.length(), 0) > 0;
        }

        std::string error_response = "ERROR: Invalid credentials\n";
        send(client.socket, error_response.c_str(), error_response.length(), 0);
        return false;
    }

    void handle_client_commands(ClientConnection& client) {
        char buffer[1024];

        while (running) {
            memset(buffer, 0, sizeof(buffer));
            int bytes_received = recv(client.socket, buffer, sizeof(buffer) - 1, 0);

            if (bytes_received <= 0) {
                std::cout << "客户端断开连接: " << client.client_address << std::endl;
                break;
            }

            std::string command(buffer);
            std::cout << "收到命令 [" << client.client_address << "]: " << command;

            Session & session = mSessions.at(std::to_string(client.sessionId));
            std::string response = index(command,session);

            std::cout << "result:::: " << response << std::endl;

            // 处理不同的命令
//            std::string response = process_command(command, client);

            if (!response.empty()) {
                send(client.socket, response.c_str(), response.length(), 0);
            }
        }
    }

    void close_client(const ClientConnection& client) {
        // 从连接列表中移除
        {
            std::lock_guard<std::mutex> lock(clients_mutex);
            clients.erase(
                    std::remove_if(clients.begin(), clients.end(),
                                   [&](const ClientConnection& c) { return c.socket == client.socket; }),
                    clients.end()
            );
        }

        // 关闭socket
#ifdef _WIN32
        closesocket(client.socket);
#else
        close(client.socket);
#endif
    }

    int server_fd;
    int port;
    bool running;
    std::vector<ClientConnection> clients;
    std::mutex clients_mutex;
};
